
#ifndef __KLIB_H__
#define __KLIB_H__

#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

int strcany(const char *str, const char *charset);
int strcsub(const char *str, const char *substr);
int strsplit(char *str, const char *delimits, char **items);
int strrep(char *str, size_t size, const char *tofind, const char *replacement);
int strrcp(char *dest, size_t size, const char *src, const char *tofind, const char *replacement);
int strcopy(char *dest, const char *src);
int strncopy(char *dest, const char *src, int count);
char *strlower(char *str);
char *strupper(char *str);
char *strlpad(char *dest, const char *src, int width, char cpad);
char *strrpad(char *dest, const char *src, int width, char cpad);
char *strtrim(char *str);
char *reverse(char *p);
char *format(const char *fmt, ...);
char *strbin(char *buffer, size_t size, unsigned int value);

char *itostr(char *buffer, int value, int radix, int width);
char *tmformat(char *buffer, size_t size, const char *fmt, struct tm* t);

char *cast_char(void *p);
int *cast_int(void *p);
float *cast_float(void *p);
double *cast_double(void *p);
long double *cast_longdouble(void *p);

int openlog(const char *filename);
int logln(int handle, const char *s);
int loglnf(int handle, const char *fmt, ...);

typedef struct _buffer_t {
	size_t	size;
	char *	data;
} buffer_t;

buffer_t *getbuf(size_t size);
void delbuf(buffer_t *buf);

typedef struct _list_node_t {
	struct _list_node_t *prev;
	struct _list_node_t *next;
	void *data;
} list_node_t;

list_node_t *list_node_create(void *data);
void list_node_destroy(list_node_t *node);
void list_insert_before(list_node_t *pos, list_node_t *node);
void list_insert_after(list_node_t *pos, list_node_t *node);
list_node_t *list_node_delete(list_node_t *node);
list_node_t *list_node_at(list_node_t *begin, int index);
list_node_t *list_head_of(list_node_t *any);
list_node_t *list_tail_of(list_node_t *any);
void list_push_back(list_node_t *any, list_node_t *node);
void list_push_front(list_node_t *any, list_node_t *node);
int list_count(const list_node_t *any);
int list_index_of(const list_node_t *node);
int list_foreach(list_node_t *begin, void (*fn_proc_node)(list_node_t *));
int list_foreach_data(list_node_t *begin, void (*fn_proc_data)(void *));

int array_create(size_t ele_size, size_t count);
void array_destroy(int handle);
void array_expand(int handle, size_t newsize);
void *array_element_at(int handle, int index);
size_t array_size(int handle);
size_t array_element_size(int handle);
void array_element_swap(int handle, int i, int j);
void array_sort(int handle, int (*compare)(const void *, const void *));

int stack_create(size_t size);
int stack_push(int handle, const void *data, size_t width);
int stack_pop(int handle, void *data, size_t width);
int stack_push_int(int handle, int value);
int stack_pop_int(int handle, int *value);
void stack_destroy(int handle);

void readcsv(const char *csvstring);

int run(int (*routine)(void *), void *arg, int interval);
void stop(int handle, int wait);

enum {
	Black = 0,
	DarkBlue = 1,
	DarkGreen = 2,
	DarkCyan = 3,
	DarkRed = 4,
	DarkMagenta = 5,
	DarkYellow = 6,
	Gray = 7,
	DarkGray = 8,
	Blue = 9,
	Green = 10,
	Cyan = 11,
	Red = 12,
	Magenta = 13,
	Yellow = 14,
	White = 15,
};

enum {
	BACK_COLOR = 0,
	FORE_COLOR = 1,
};

int termcolor(int type, int c);
int cprint(int color, const char *str);
int cprintln(int color, const char *str);

void *get_element_int(void *base, int index);
void *get_element_long(void *base, int index);
void *get_element_float(void *base, int index);
void *get_element_double(void *base, int index);
void *get_element_ptr(void *base, int index);

int compare_int(const void *v1, const void *v2);
int compare_int_r(const void *v1, const void *v2);
int compare_long(const void *v1, const void *v2);
int compare_long_r(const void *v1, const void *v2);
int compare_double(const void *v1, const void *v2);
int compare_longdouble(const void *v1, const void *v2);
int compare_double_r(const void *v1, const void *v2);
int compare_longdouble_r(const void *v1, const void *v2);

void *max2(void *a, void *b, int (*compare)(const void *, const void *));
void *min2(void *a, void *b, int (*compare)(const void *, const void *));
void *max3(void *a, void *b, void *c, int (*compare)(const void *, const void *));
void *min3(void *a, void *b, void *c, int (*compare)(const void *, const void *));
void *mid3(void *a, void *b, void *c, int (*compare)(const void *, const void *));
int midx(void *base, int i, int j, int k, void *(*get_element)(void *, int), int (*compare)(const void *, const void *));

void swap(void *a, void *b, int width);
void swap_int(void *base, int i, int j);
void swap_ptr(void *base, int i, int j);
void swap_double(void *base, int i, int j);
void swap_longdouble(void *base, int i, int j);

typedef void *(*fn_get_element_t)(void *, int);
typedef void (*fn_swap_t)(void *, int, int);
void quicksort(void *base, void *(*get_element)(void *, int), int left, int right, int (*compare)(const void *, const void *), void (*swap)(void *, int, int));
void insertsort(void *base, void *(*get_element)(void *, int), int left, int right, int (*compare)(const void *, const void *), void (*swap)(void *, int, int));

#ifdef __cplusplus
}
#endif

#endif
